package com.youlu.campus.service.qa.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.base.exception.QaMaxLimitException;
import com.youlu.campus.common.utils.ExcelUtil;
import com.youlu.campus.common.utils.TimeUtils;
import com.youlu.campus.entity.ActivityInfo;
import com.youlu.campus.entity.ActivityPlatformConfig;
import com.youlu.campus.entity.ActivityQaInfo;
import com.youlu.campus.entity.ActivityQuestionInfo;
import com.youlu.campus.entity.ActivityTaskInfo;
import com.youlu.campus.entity.ActivityTaskRule;
import com.youlu.campus.entity.CertificateActivityConfig;
import com.youlu.campus.entity.UserActivityPointDetail;
import com.youlu.campus.service.ranking.entity.UserActivityPointRanking;
import com.youlu.campus.entity.UserActivityTaskInfo;
import com.youlu.campus.entity.UserInfoExtend;
import com.youlu.campus.entity.UserPO;
import com.youlu.campus.entity.UserParticipateActivityInfo;
import com.youlu.campus.entity.UserParticipateActivityTaskInfo;
import com.youlu.campus.entity.UserQaInfo;
import com.youlu.campus.entity.UserQaLevel;
import com.youlu.campus.entity.UserQaRanking;
import com.youlu.campus.entity.VO.req.QaCommitCommand;
import com.youlu.campus.entity.VO.req.QaInfoReq;
import com.youlu.campus.entity.VO.req.QaPracticeCommitCommand;
import com.youlu.campus.entity.VO.req.UserCaReceivePointReq;
import com.youlu.campus.entity.VO.req.UserQaQueryVO;
import com.youlu.campus.entity.VO.res.ActivityPlusUserQaRes;
import com.youlu.campus.entity.VO.res.H5QaPracticeErrorQuery;
import com.youlu.campus.entity.VO.res.H5UserQaPracticeRes;
import com.youlu.campus.entity.VO.res.QQUserQaRes;
import com.youlu.campus.entity.VO.res.QaInfoScoreResponse;
import com.youlu.campus.entity.VO.res.QaRuleMatchRes;
import com.youlu.campus.entity.VO.res.UserQaInviteInfoRes;
import com.youlu.campus.entity.VO.res.UserQaPracticeResult;
import com.youlu.campus.entity.ca.UserCa;
import com.youlu.campus.entity.course.UserCourseOrder;
import com.youlu.campus.entity.domain.UserQaImportDomain;
import com.youlu.campus.entity.english.UserCompetitionQa;
import com.youlu.campus.entity.english.UserCompetitionQaAnswer;
import com.youlu.campus.entity.english.UserQuestionInfo;
import com.youlu.campus.entity.english.vo.request.QueryQaHomeCommand;
import com.youlu.campus.entity.english.vo.response.UserQaInfoResponse;
import com.youlu.campus.entity.english.vo.response.UserQaScoreResponse;
import com.youlu.campus.entity.enums.CourseOrderStatusEnum;
import com.youlu.campus.entity.enums.TaskBizType;
import com.youlu.campus.service.activity.ActivityPlatformConfigService;
import com.youlu.campus.service.activity.ActivityService;
import com.youlu.campus.service.activity.ActivityTaskRuleService;
import com.youlu.campus.service.activity.ActivityTaskService;
import com.youlu.campus.service.activity.UserActivityTaskInfoService;
import com.youlu.campus.service.activity.UserParticipateActivityInfoService;
import com.youlu.campus.service.activity.WechatMiniQaService;
import com.youlu.campus.service.ca.GenerateUserCaService;
import com.youlu.campus.service.ca.UserCaService;
import com.youlu.campus.service.ca.impl.CertificateActivityConfigService;
import com.youlu.campus.service.course.UserCourseOrderService;
import com.youlu.campus.service.english.CompetitionQaInfoService;
import com.youlu.campus.service.invite.UserInviteRecordService;
import com.youlu.campus.service.qa.ActivityQaInfoService;
import com.youlu.campus.service.qa.UserCompetitionQaAnswerService;
import com.youlu.campus.service.qa.UserQaInfoService;
import com.youlu.campus.service.ranking.UserActivityPointDetailService;
import com.youlu.campus.service.ranking.UserActivityPointRankingProvinceService;
import com.youlu.campus.service.ranking.UserActivityPointRankingService;
import com.youlu.campus.service.visitor.UserInfoExtendService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class UserQaInfoServiceImpl implements UserQaInfoService {


    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private ActivityQaInfoService activityQaInfoService;


    @Autowired
    private UserInfoExtendService userInfoExtendService;

    @Autowired
    private CertificateActivityConfigService certificateActivityConfigService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    public final static String USER_QA_LOCK = "campus:qa:commit:lock:%s:%s";

    private final static String USER_QA_DAY_LOCK = "campus:qa:commit:daylock:%s:%s:%s";

    @Autowired
    public CompetitionQaInfoService competitionQaInfoService;

    @Autowired
    private UserCaService userCaService;

    @Autowired
    private ActivityPlatformConfigService activityPlatformConfigService;

    @Autowired
    private UserInviteRecordService userInviteRecordService;

    @Autowired
    private ActivityTaskService activityTaskService;

    @Lazy
    @Autowired
    private UserParticipateActivityInfoService userParticipateActivityInfoService;

    @Autowired
    private UserQaRankingService userQaRankingService;


    @Autowired
    private ActivityTaskRuleService activityTaskRuleService;

    @Autowired
    private UserActivityPointRankingService userActivityPointRankingService;

    @Autowired
    private GenerateUserCaService generateUserCaService;

    @Autowired
    private UserActivityTaskInfoService userActivityTaskInfoService;

    @Autowired
    private UserActivityPointDetailService userActivityPointDetailService;

    @Lazy
    @Autowired
    private ActivityService activityService;


    @Autowired
    private UserCompetitionQaAnswerService userCompetitionQaAnswerService;


    @Autowired
    private UserActivityPointRankingProvinceService userActivityPointRankingProvinceService;

    @Lazy
    @Autowired
    private UserCourseOrderService userCourseOrderService;
    @Lazy
    @Autowired
    private WechatMiniQaService wechatMiniQaService;

    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
        list.removeIf(integer -> integer == 1);
        System.out.println(list);
    }


    @Async
    @Override
    public void create(UserQaInfo req) {
        log.info(":>>> 开始新增用户答题:{}", JSON.toJSONString(req));
        ActivityQaInfo activityQaInfo = this.mongoTemplate.findById(req.getActivityQaInfoId(), ActivityQaInfo.class);
        Double qaScore = req.getQaScore();
        Date now = new Date();
        Query query = getQaQuery(req.getUserId(), req.getActivityQaInfoId(), req.getActivityId());
        Update update = new Update();
        UserQaInfo existsUserQaInfo = this.mongoTemplate.findOne(query, UserQaInfo.class);
        if (Objects.isNull(existsUserQaInfo)) {
            update.set("createdTime", now);
            update.set("qaScore", qaScore);
            if (qaScore.intValue() >= activityQaInfo.getPassQaScore().intValue()) {
                update.set("passed", Boolean.TRUE);
                update.set("accumulateQ", Boolean.TRUE);
                //增加用户参与活动答题贡献值
                // addPoint(req.getCurrentUser(), req.getActivityId());
            } else {
                update.set("passed", Boolean.FALSE);
                update.set("accumulateQ", Boolean.FALSE);
            }
        }
        QaRuleMatchRes qaRuleMatchRes = competitionQaInfoService.qaRuleByQaInfoId(activityQaInfo.getId(), qaScore);
        String caLevelName = qaRuleMatchRes.getCaLevelName();
        UserQaLevel userQaLevel = new UserQaLevel();
        userQaLevel.setActivityQaInfoId(req.getActivityQaInfoId());
        userQaLevel.setQsScore(qaScore);
        userQaLevel.setQaNumber(activityQaInfo.getNo());
        userQaLevel.setLevel(caLevelName);
        userQaLevel.setHighestLevel(qaRuleMatchRes.getHighestLevel());
        update.push("userQaLevelList", userQaLevel);
        update.push("scoreSet", qaScore);
        update.set("updatedTime", now);
        update.set("status", "1");
        update.set("activityName", activityQaInfo.getActivityName());
        update.set("totalQaNum", activityQaInfo.getTotalQaNum());
        update.inc("reTryQaNum", 1);
        update.set("no", activityQaInfo.getNo());
        update.set("caName", req.getCaName());
        if (Objects.nonNull(existsUserQaInfo) && qaScore.compareTo(existsUserQaInfo.getQaScore()) == 1) {
            update.set("qaScore", qaScore);
            if (qaScore.intValue() >= activityQaInfo.getPassQaScore().intValue()) {
                update.set("passed", Boolean.TRUE);
                // 增加用户参与活动答题贡献值如果已经加加奖励，则无需加
                if (!existsUserQaInfo.getAccumulateQ()) {
                    //  addPoint(req.getCurrentUser(), activityQaInfo.getActivityId());
                    update.set("accumulateQ", Boolean.TRUE);
                }
            } else {
                update.set("passed", Boolean.FALSE);
            }
        }
        FindAndModifyOptions findAndModifyOptions = new FindAndModifyOptions();
        findAndModifyOptions.upsert(Boolean.TRUE);
        findAndModifyOptions.returnNew(Boolean.TRUE);
        this.mongoTemplate.findAndModify(query, update, findAndModifyOptions, UserQaInfo.class);
    }

    @Override
    public boolean update(UserQaInfo req) {
        if (Objects.isNull(req) || !StringUtils.isNotBlank(req.getId())) {
            log.error(":>>> 修改用户答题记录参数错误:ID未空");
            return false;
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(req.getId()));
        Update update = new Update();
        if (Objects.nonNull(req.getReTryQaNum())) {
            update.set("reTryQaNum", req.getReTryQaNum());
        }
        if (Objects.nonNull(req.getTotalQaNum())) {
            update.set("totalQaNum", req.getTotalQaNum());
        }
        if (Objects.nonNull(req.getBuyQaNum())) {
            update.set("buyQaNum", req.getBuyQaNum());
        }
        if (Objects.nonNull(req.getQaScore())) {
            update.set("qaScore", req.getQaScore());
        }
        if (StringUtils.isNotBlank(req.getCaName())) {
            update.set("caName", req.getCaName());
        }
        update.set("updatedTime", new Date());
        return mongoTemplate.updateFirst(query, update, UserQaInfo.class).getModifiedCount() > 0 ? true : false;
    }

    @Override
    public List<UserQaInfo> list(UserQaInfo req) {
        if (Objects.isNull(req)) {
            return null;
        }
        Query query = new Query();
        if (StringUtils.isBlank(req.getUserId())) {
            query.addCriteria(Criteria.where("userId").is(req.getUserId()));
        }
        if (StringUtils.isBlank(req.getActivityId())) {
            query.addCriteria(Criteria.where("activityId").is(req.getActivityId()));
        }
        return mongoTemplate.find(query, UserQaInfo.class);
    }

    @Override
    public boolean updateByQaNo(String userId, String activityId, Integer qaNo, Double score) {
        if (StringUtils.isBlank(userId) || StringUtils.isBlank(activityId) || Objects.isNull(qaNo) || Objects.isNull(score)) {
            log.error(":>>> 修改答题分数参数错误:用户ID、活动ID、答题编号、分数为空");
            return false;
        }
        Query query =
                new Query().addCriteria(Criteria.where("userId").is(userId).and("activityId").is(activityId).and("no").is(qaNo));
        Update update = new Update();
        update.set("score", score);
        update.set("updatedTime", new Date());
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, UserQaInfo.class);
        return updateResult.getModifiedCount() > 0 ? true : false;
    }

    @Override
    public QQUserQaRes findByActivityId(UserPO currentUser, String activityId) {
        List<ActivityQaInfo> qaInfoList = this.activityQaInfoService.findByActivityId(activityId);
        if (CollectionUtils.isEmpty(qaInfoList)) {
            throw new BusinessException("当前活动未配置答题信息");
        }
        Optional<ActivityQaInfo> chuSaiQaOptional =
                qaInfoList.parallelStream().filter(activityQaInfo -> activityQaInfo.getNo() == 1).findAny();
        if (!chuSaiQaOptional.isPresent()) {
            throw new BusinessException("当前活动未配置校赛答题");
        }
        Optional<ActivityQaInfo> fuSaiQaOptional =
                qaInfoList.parallelStream().filter(activityQaInfo -> activityQaInfo.getNo() == 2).findAny();
        if (!fuSaiQaOptional.isPresent()) {
            throw new BusinessException("当前活动未配置省赛答题");
        }
        Optional<ActivityQaInfo> jueSaiQaOptional =
                qaInfoList.parallelStream().filter(activityQaInfo -> activityQaInfo.getNo() == 3).findAny();
        if (!jueSaiQaOptional.isPresent()) {
            throw new BusinessException("当前活动未配置国赛答题");
        }
        ActivityInfo activityInfo = activityService.findOne(activityId);
        QQUserQaRes userQa = new QQUserQaRes();
        ActivityQaInfo chuSaiActivityQaInfo = chuSaiQaOptional.get();
        ActivityQaInfo fuSaiActivityQaInfo = fuSaiQaOptional.get();
        ActivityQaInfo jueSaiActivityQaInfo = jueSaiQaOptional.get();
        String chuSaiQaId = chuSaiActivityQaInfo.getId();
        String fuSaiQaId = fuSaiActivityQaInfo.getId();
        String jueSaiQaId = jueSaiActivityQaInfo.getId();
        userQa.setChuSaiQaId(chuSaiQaId);
        userQa.setFuSaiQaId(fuSaiQaId);
        userQa.setJueSaiQaId(jueSaiQaId);
        userQa.setChuSaiQaPassed(Boolean.TRUE);
        userQa.setHeaderImageUrl(activityInfo.getHeaderImageUrl());
        userQa.setActivityDetail(activityInfo.getDetail());
        List<UserQaInfo> userQaInfoList = getUserQaInfos(currentUser, activityId, chuSaiQaId, fuSaiQaId, jueSaiQaId);
        if (CollectionUtils.isEmpty(userQaInfoList)) {
            userQa.setFuSaiQaPassed(Boolean.FALSE);
            userQa.setJueSaiQaPassed(Boolean.FALSE);
            return userQa;
        }
        Optional<UserQaInfo> chuSaiOptional = checkUserQaInfo(chuSaiQaId, userQaInfoList);
        if (chuSaiOptional.isPresent()) {
            userQa.setFuSaiQaPassed(Boolean.TRUE);
        }
        Optional<UserQaInfo> fuSaiOptional = checkUserQaInfo(fuSaiQaId, userQaInfoList);
        if (fuSaiOptional.isPresent()) {
            userQa.setFuSaiQaPassed(Boolean.TRUE);
            userQa.setJueSaiQaPassed(Boolean.TRUE);
        }
        return userQa;
    }

    @Override
    public UserQaScoreResponse doQaCommit(QaCommitCommand qaCommitCommand) {
        UserPO currentUser = qaCommitCommand.getCurrentUser();
        String userId = currentUser.getId();
        String qaInfoId = qaCommitCommand.getQaInfoId();
        List<ActivityQuestionInfo> userAnswersQuestionInfoList = qaCommitCommand.getUserAnswersQuestionInfoList();
        Boolean existLockKey = redisTemplate.opsForValue().setIfAbsent(String.format(USER_QA_LOCK, userId, qaInfoId),
                "1", 4L, TimeUnit.SECONDS);
        if (Objects.nonNull(existLockKey) && !existLockKey) {
            throw new BusinessException("对不起哦，服务繁忙,稍后重试");
        }
        ActivityQaInfo activityQaInfo = this.mongoTemplate.findById(qaInfoId, ActivityQaInfo.class);
        List<String> userSubmitQuestionIdList =
                userAnswersQuestionInfoList.stream().map(userAnswer -> userAnswer.getId()).collect(Collectors.toList());
        List<ActivityQuestionInfo> questionInfoList = queryQaInfoId(qaInfoId, userSubmitQuestionIdList);
        ActivityInfo activityInfo = activityService.findOne(activityQaInfo.getActivityId());
        UserInfoExtend userInfoExtend = null;
        if (qaCommitCommand.getType() == 1 || qaCommitCommand.getType() == 3) {
            userInfoExtend = userInfoExtendService.findByUserId(currentUser.getId());
            if (activityQaInfo.getNo() != 1) {
                if (Objects.isNull(userInfoExtend)) {
                    throw new BusinessException("对不起，您未报名不能进行答题");
                }
            }
        } else {
            //宗瑞新业务获取用户报名信息
            userInfoExtend = new UserInfoExtend();
            UserParticipateActivityInfo userParticipateActivityInfo =
                    userParticipateActivityInfoService.findByUserIdActivityId(userId, activityQaInfo.getActivityId());
            if (Objects.nonNull(userParticipateActivityInfo)) {
                userInfoExtend.setMobile(userParticipateActivityInfo.getMobile());
                userInfoExtend.setUserId(userId);
                userInfoExtend.setNickName(currentUser.getNickName());
                userInfoExtend.setAvatarUrl(currentUser.getAvatarUrl());
                userInfoExtend.setUniversityId(userParticipateActivityInfo.getUniversityId());
                userInfoExtend.setUniversityName(userParticipateActivityInfo.getUniversityName());
                userInfoExtend.setName(userParticipateActivityInfo.getName());
            }
        }
        if (qaCommitCommand.getType() == 3 || qaCommitCommand.getType() == 6) {
            log.info("【每日知识挑战】userId- > {} qaInfoId -> {} ", userId, qaInfoId);
            //验证用户当天答题限制1次
            Boolean existQaLockKey = redisTemplate.opsForValue().setIfAbsent(String.format(USER_QA_DAY_LOCK, userId,
                    qaInfoId,
                    LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))), "1", 1, TimeUnit.DAYS);
            if (Objects.nonNull(existQaLockKey) && !existQaLockKey) {
                log.info("【每日知识挑战】userId- > {} qaInfoId -> {} 今日答题已完成,请明日再来", userId, qaInfoId);
                throw new BusinessException("今日答题已完成,请明日再来");
            }
        }
        UserQaScoreResponse userQaScore = new UserQaScoreResponse();
        userQaScore.setQaInfoId(qaInfoId);
        userQaScore.setActivityId(activityQaInfo.getActivityId());
        if (Objects.nonNull(userInfoExtend)) {
            userQaScore.setRegister(Boolean.TRUE);
        }
        QaInfoScoreResponse userQaInfoScore = competitionQaInfoService.getQaScore(currentUser.getId(), qaInfoId,
                questionInfoList, userAnswersQuestionInfoList);
        Double qaScore = userQaInfoScore.getQaScore();
        userQaInfoScore.clear();
        userQaScore.setScore(qaScore.toString() + "分");
        if ((qaCommitCommand.getType() != 3 && qaCommitCommand.getType() != 6) && qaScore.intValue() == 0D) {
            userQaScore.setTipsScore("很遗憾,未获奖");
            userQaScore.setButtonText("重新考试");
            userQaScore.setRestQa(Boolean.TRUE);
            return userQaScore;
        }
        log.info("【提交答题】用户->{}参与了答题 - > {} | 分数->{}", currentUser.getId(), qaInfoId, qaScore);
        String caLevelName = "";
        if (qaCommitCommand.getType() != 3 && qaCommitCommand.getType() != 6) {
            QaRuleMatchRes qaRuleMatchRes = competitionQaInfoService.qaRuleByQaInfoId(qaInfoId, qaScore);
            caLevelName = qaRuleMatchRes.getCaLevelName();
            log.info("【提交答题】用户->{}参与了答题 - > {} | 分数->{} 等级 - > {}", currentUser.getId(), qaInfoId, qaScore,
                    caLevelName);
        }
        userQaScore.setCaLevel(caLevelName);
        Double passQaScore = activityQaInfo.getPassQaScore();
        FindAndModifyOptions findAndModifyOptions = new FindAndModifyOptions();
        findAndModifyOptions.upsert(Boolean.TRUE);
        findAndModifyOptions.returnNew(Boolean.TRUE);
        Date now = new Date();
        Query query = getQaQuery(userId, qaInfoId, activityQaInfo.getActivityId());
        Update update = new Update();
        UserQaInfo existsUserQaInfo = this.mongoTemplate.findOne(query, UserQaInfo.class);
        if (Objects.isNull(existsUserQaInfo)) {
            update.set("createdTime", now);
            update.set("qaScore", qaScore);
            if (qaScore.intValue() >= passQaScore.intValue()) {
                update.set("passed", Boolean.TRUE);
                update.set("accumulateQ", Boolean.TRUE);
                if (qaCommitCommand.getType() == 4) {
                    addPointH5(currentUser, activityQaInfo);
                } else {
                    if (qaCommitCommand.getType() != 3 && qaCommitCommand.getType() != 6) {
                        //增加用户参与活动答题贡献值
                        addPoint(currentUser, activityQaInfo.getActivityId());
                    }
                }
            } else {
                update.set("passed", Boolean.FALSE);
                update.set("accumulateQ", Boolean.FALSE);
            }
        }

        if (qaCommitCommand.getType() == 1) {
            checkQaLimit(1, userId, qaInfoId);
        } else {
            //每日提交答题答题次数限制
            if (qaCommitCommand.getType() != 6) {
                checkQaLimit(2, userId, qaInfoId);
            }
        }
        UserParticipateActivityInfo userParticipateActivityInfo = null;
        if (qaCommitCommand.getType() != 3 && qaCommitCommand.getType() != 6) {
            //购买新增报名信息
            userParticipateActivityInfo = new UserParticipateActivityInfo();
            userParticipateActivityInfo.setActivityId(activityQaInfo.getActivityId());
            userParticipateActivityInfo.setUserId(currentUser.getId());
            userParticipateActivityInfo.setTotalQaNum(activityQaInfo.getTotalQaNum());
            if (activityQaInfo.getNo() == 2 || activityQaInfo.getNo() == 6) {
                userParticipateActivityInfo.setProvinceQaScore(qaScore);
            } else if (activityQaInfo.getNo() == 3 || activityQaInfo.getNo() == 7) {
                userParticipateActivityInfo.setCountryQaScore(qaScore);
            } else {
                userParticipateActivityInfo.setQaScore(qaScore);
            }
            userParticipateActivityInfo.setCurrentQaScore(qaScore);
            userParticipateActivityInfo.setPassQaScore(activityQaInfo.getPassQaScore());
            if (Objects.isNull(existsUserQaInfo)) {
                userParticipateActivityInfo.setReTryQaNum(activityQaInfo.getTotalQaNum() - 1);
            } else {
                userParticipateActivityInfo.setReTryQaNum(existsUserQaInfo.getReTryQaNum());
            }
            if (Objects.nonNull(userInfoExtend)) {
                userParticipateActivityInfo.setUniversityId(userInfoExtend.getUniversityId());
                userParticipateActivityInfo.setUniversityName(userInfoExtend.getUniversityName());
                userParticipateActivityInfo.setName(userInfoExtend.getName());
                userParticipateActivityInfo.setMobile(userInfoExtend.getMobile());
                userParticipateActivityInfo.setGrade(userInfoExtend.getGrade());
                userParticipateActivityInfo.setNickName(userInfoExtend.getNickName());
                userParticipateActivityInfo.setJoined(Boolean.TRUE);
            }
            if (qaScore.intValue() >= passQaScore.intValue()) {
                userParticipateActivityInfo.setPassed(Boolean.TRUE);
            }
            userParticipateActivityInfo.setContestCaName(caLevelName);
            this.userParticipateActivityInfoService.saveOrUpdate(userParticipateActivityInfo);
        }
        UserQaLevel userQaLevel = new UserQaLevel();
        userQaLevel.setActivityQaInfoId(activityQaInfo.getId());
        userQaLevel.setQaNumber(activityQaInfo.getNo());
        userQaLevel.setQsScore(qaScore);
        userQaLevel.setLevel(caLevelName);
        update.push("userQaLevelList", userQaLevel);
        update.push("scoreSet", qaScore);
        update.set("updatedTime", now);
        update.set("status", "1");
        update.set("activityName", activityQaInfo.getActivityName());
        update.inc("reTryQaNum", 1);
        update.set("totalQaNum", activityQaInfo.getTotalQaNum());
        update.set("no", activityQaInfo.getNo());
        update.set("caName", caLevelName);
        if (Objects.nonNull(existsUserQaInfo) && qaScore.compareTo(existsUserQaInfo.getQaScore()) == 1) {
            update.set("qaScore", qaScore);
            if (qaScore.intValue() >= passQaScore.intValue()) {
                update.set("passed", Boolean.TRUE);
                // 增加用户参与活动答题贡献值如果已经加加奖励，则无需加
                if (!existsUserQaInfo.getAccumulateQ()) {
                    if (qaCommitCommand.getType() == 4) {
                        addPointH5(currentUser, activityQaInfo);
                    } else {
                        if (qaCommitCommand.getType() != 3 && qaCommitCommand.getType() != 6) {
                            //增加用户参与活动答题贡献值
                            addPoint(currentUser, activityQaInfo.getActivityId());
                        }
                    }
                    update.set("accumulateQ", Boolean.TRUE);
                }
            } else {
                update.set("passed", Boolean.FALSE);
            }
        }
        if (qaCommitCommand.getType() == 2 || qaCommitCommand.getType() == 5) {
            //增加用户分数
            UserQaRanking userQaRanking = new UserQaRanking();
            userQaRanking.setActivityId(activityQaInfo.getActivityId());
            userQaRanking.setQaInfoId(qaInfoId);
            userQaRanking.setQaNo(activityQaInfo.getNo());
            userQaRanking.setUserId(userId);
            userQaRanking.setHeadImageUrl(currentUser.getAvatarUrl());
            userQaRanking.setQaScore(qaScore);
            userQaRanking.setQaTitle(activityQaInfo.getName());
            userQaRanking.setNickName(currentUser.getNickName());
            if (Objects.nonNull(userParticipateActivityInfo)) {
                userQaRanking.setUniversityId(userParticipateActivityInfo.getUniversityId());
                userQaRanking.setUniversityName(userParticipateActivityInfo.getUniversityName());
            }
            this.userQaRankingService.saveOrUpdate(userQaRanking);
        }
        UserQaInfo userQaInfo = this.mongoTemplate.findAndModify(query, update, findAndModifyOptions, UserQaInfo.class);
        if (Objects.isNull(userQaInfo)) {
            if (qaCommitCommand.getType() == 1) {
                userQaScore.setTipsScore("很遗憾,答题未及格，请继续答题");
                userQaScore.setButtonText("重新答题");
            } else {
                userQaScore.setTipsScore("很遗憾,考试未及格，请继续考试");
                userQaScore.setButtonText("重新考试");
            }
            userQaScore.setQaErrorCount(userQaInfoScore.getQaErrorCount());
            userQaScore.setQaRightCount(userQaInfoScore.getQaRightCount());
            userQaScore.setRestQa(Boolean.TRUE);
            return userQaScore;
        }
        //新QQ小程序
        if (qaCommitCommand.getType() == 3 || qaCommitCommand.getType() == 6) {
            log.info("【每日知识挑战】userId- > {} qaInfoId -> {} ", userId, qaInfoId);
            userQaScore.setQaErrorCount(userQaInfoScore.getQaErrorCount());
            userQaScore.setQaRightCount(userQaInfoScore.getQaRightCount());
            userQaScore.setQaScore(qaScore.intValue());
            if (StringUtils.isNotBlank(activityInfo.getRewardValueAlias())) {
                userQaScore.setRewardValueAlias(activityInfo.getRewardValueAlias());
            }
            //增加完成每日答题任务
            UserActivityTaskInfo userActivityTaskInfo = new UserActivityTaskInfo();
            userActivityTaskInfo.setActivityId(activityQaInfo.getActivityId());
            userActivityTaskInfo.setDayTime(TimeUtils.getDayStartTime(now));
            userActivityTaskInfo.setDoneTime(now);
            userActivityTaskInfo.setTaskBizType(TaskBizType.KNOWLEDGE_CHALLENGE);
            userActivityTaskInfo.setUserId(currentUser.getId());
            userActivityTaskInfo.setStatus(2);
            userActivityTaskInfo.setDoType("day");
            userActivityTaskInfoService.createTask(userActivityTaskInfo);
            if (qaScore > 0) {
                //增加活力值和活力值记录
                UserActivityPointDetail userActivityPointDetail = new UserActivityPointDetail();
                userActivityPointDetail.setAction("add");
                userActivityPointDetail.setActivityId(activityQaInfo.getActivityId());
                userActivityPointDetail.setBizDesc("每日知识挑战");
                userActivityPointDetail.setComments("每日知识挑战" + userQaScore.getQaScore());
                userActivityPointDetail.setBizType("qa");
                userActivityPointDetail.setOptDate(new Date());
                userActivityPointDetail.setPoints(userQaScore.getQaScore());
                userActivityPointDetail.setUserId(currentUser.getId());
                userActivityPointDetail.setUserPO(currentUser);
                userActivityPointDetailService.create(userActivityPointDetail);
                //增加活力值省榜
                userActivityPointRankingProvinceService.updatePoint(currentUser, activityInfo.getId(),
                        userQaScore.getQaScore());

            }
            //移除选题
            query = new Query();
            query.addCriteria(Criteria.where("userId").is(userId));
            query.addCriteria(Criteria.where("activityQaInfoId").is(qaInfoId));
            query.addCriteria(Criteria.where("activityId").is(activityQaInfo.getActivityId()));
            this.mongoTemplate.remove(query, UserQuestionInfo.class);
            return userQaScore;
        }

        if (qaScore.intValue() < passQaScore.intValue()) {
            if (qaCommitCommand.getType() == 1) {
                userQaScore.setTipsScore("很遗憾,答题未及格，请继续答题");
                userQaScore.setButtonText("重新答题");
            } else {
                //H5老版本答题
                if (qaCommitCommand.getType() == 4 || qaCommitCommand.getType() == 5) {
                    userQaScore.setTipsScore("很遗憾,未获奖");
                    userQaScore.setButtonText("重新答题");
                } else {
                    userQaScore.setTipsScore("很遗憾,考试未及格，请继续考试");
                    userQaScore.setButtonText("重新考试");
                }
            }
            userQaScore.setRestQa(Boolean.TRUE);
            return userQaScore;
        }

        if (qaCommitCommand.getType() != 4 || qaCommitCommand.getType() != 6) {
            Optional<CertificateActivityConfig> certificateActivityConfigOptional =
                    getCertificateActivityConfig(qaCommitCommand.getType(), activityQaInfo, activityInfo);
            UserCa userCa = new UserCa();
            if (certificateActivityConfigOptional.isPresent()) {
                CertificateActivityConfig certificateActivityConfig = certificateActivityConfigOptional.get();
                userCa.setCertificateActivityConfigId(certificateActivityConfig.getId());
                userCa.setCaType(certificateActivityConfig.getCaType());
                userCa.setCertificateName(certificateActivityConfig.getCertificateName());
                userQaScore.setCaType(certificateActivityConfig.getCaType());
            }
            userCa.setCaLevel(caLevelName);
            userCa.setActivityId(activityQaInfo.getActivityId());
            userCa.setMoneyType("3");
            userCa.setActivityName(activityQaInfo.getActivityName());
            //获取用户信息
            if (Objects.nonNull(userInfoExtend)) {
                userCa.setUniversityId(userInfoExtend.getUniversityId());
                userCa.setUniversityName(userInfoExtend.getUniversityName());
                userCa.setName(userInfoExtend.getName());
                userCa.setMobile(userInfoExtend.getMobile());
                userCa.setGrade(userInfoExtend.getGrade());
            }
            userCa.setTaskBizType("qa");
            userCa.setUserId(userId);
            userCa.setScore(qaScore);
            userCa.setPlatform(currentUser.getCurrentPlatform());
            userCa.setAppId(currentUser.getAppId());
            //生成用户证书信息
            userCaService.create(userCa);
        }
        //记录用户答题
        UserCompetitionQaAnswer userCompetitionQa = new UserCompetitionQaAnswer();
        userCompetitionQa.setAnswersQuestionInfoList(userAnswersQuestionInfoList);
        userCompetitionQa.setQaInfoId(qaInfoId);
        userCompetitionQa.setUserId(currentUser.getId());
        userCompetitionQa.setScore(qaScore);
        userCompetitionQa.setActivityGroupId(activityQaInfo.getActivityId());
        this.mongoTemplate.save(userCompetitionQa);
        //移除选题
        query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        query.addCriteria(Criteria.where("activityQaInfoId").is(qaInfoId));
        query.addCriteria(Criteria.where("activityId").is(activityQaInfo.getActivityId()));
        this.mongoTemplate.remove(query, UserQuestionInfo.class);
        UserCaReceivePointReq userCaReceivePointReq = new UserCaReceivePointReq();
        userCaReceivePointReq.setCurrentUser(currentUser);
        userCaReceivePointReq.setCaType(userQaScore.getCaType());
        userCaReceivePointReq.setActivityId(activityQaInfo.getActivityId());
        userCaReceivePointReq.setBizType("recieve-digit-ca");
        if (qaCommitCommand.getType() == 1) {
            userQaScore.setTipsScore("获得" + caLevelName);
            userQaScore.setButtonText("领取证书");
            return userQaScore;
        }
        userQaScore.setTipsScore("恭喜，获得" + caLevelName);
        userQaScore.setButtonText("领取证书");
        return userQaScore;
    }

    @Override
    public Optional<CertificateActivityConfig> getCertificateActivityConfig(Integer type,
                                                                            ActivityQaInfo activityQaInfo,
                                                                            ActivityInfo activityInfo) {
        String matchesRegexKey = "";
        Optional<CertificateActivityConfig> certificateActivityConfigOptional = null;
        List<CertificateActivityConfig> certificateActivityConfigList =
                certificateActivityConfigService.findByActivityId(activityQaInfo.getActivityId());
        if (CollectionUtils.isEmpty(certificateActivityConfigList)) {
            throw new BusinessException("未配置证书信息");
        }
        String chuSaiKeyWord = "";
        String fuSaiKeyWord = "";
        String jueSaiKeyWord = "";
        if (type == 5) {
            HashMap<String, String> caMatchKeyMap = activityInfo.getCaMatchKeyWords();
            if (MapUtils.isEmpty(caMatchKeyMap)) {
                throw new BusinessException("证书领取关键字信息未配置");
            }
            //初赛匹配
            chuSaiKeyWord = caMatchKeyMap.get("c-contest");
            //复赛匹配
            fuSaiKeyWord = caMatchKeyMap.get("p-contest");
            //决赛匹配
            jueSaiKeyWord = caMatchKeyMap.get("co-contest");
        }

        Integer no = activityQaInfo.getNo();
        if (type == 1) {
            switch (no) {
                case 1:
                    matchesRegexKey = ".*(校赛).*";
                    break;
                case 2:
                    matchesRegexKey = ".*(省赛).*";
                    break;
                case 3:
                    matchesRegexKey = ".*(国赛).*";
                    break;
                default:
                    matchesRegexKey = ".*(校赛).*";
            }
        } else {
            //新业务
            switch (no) {
                case 1:
                    chuSaiKeyWord = StringUtils.isEmpty(chuSaiKeyWord) ? "初赛" : chuSaiKeyWord;
                    matchesRegexKey = String.format(".*(%s).*", chuSaiKeyWord);
                    break;
                case 2:
                    fuSaiKeyWord = StringUtils.isEmpty(fuSaiKeyWord) ? "复赛" : fuSaiKeyWord;
                    matchesRegexKey = String.format(".*(%s).*", fuSaiKeyWord);

                    break;
                case 3:
                    jueSaiKeyWord = StringUtils.isEmpty(jueSaiKeyWord) ? "决赛" : jueSaiKeyWord;
                    matchesRegexKey = String.format(".*(%s).*", jueSaiKeyWord);
                    break;
                default:
                    matchesRegexKey = ".*(初赛).*";
            }
        }

        //获取证书信息
        String finalMatchesRegexKey = matchesRegexKey;
        if (type == 1) {
            certificateActivityConfigOptional =
                    certificateActivityConfigList.stream().filter(certificateActivityConfig -> certificateActivityConfig.getCertificateName().matches(finalMatchesRegexKey)).findAny();
        } else {
            certificateActivityConfigOptional =
                    certificateActivityConfigList.stream().filter(certificateActivityConfig -> certificateActivityConfig.getCaType().matches(finalMatchesRegexKey)).findAny();
        }
        return certificateActivityConfigOptional;
    }

    @Async
    @Override
    public void removePassedRefundQa(String userId, String activityId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        query.addCriteria(Criteria.where("activityId").is(activityId));
        this.mongoTemplate.remove(query, UserQaInfo.class);
    }

    @Override
    public Page<UserQaInfo> list(UserQaQueryVO req) {
        log.info(":>>> 开始获取用户答题题库等分记录:{}", JSON.toJSON(req));
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(req.getUserId()));
        query.addCriteria(Criteria.where("activityId").is(req.getActivityId()));
        long count = this.mongoTemplate.count(query, UserQaInfo.class);
        PageRequest pageRequest = PageRequest.of(req.getPage() - 1, req.getPageSize());
        if (count == 0) {
            return PageableExecutionUtils.getPage(new ArrayList<>(), pageRequest, () -> count);
        }
//        query.with(new Sort(Sort.Direction.DESC, "createdTime"));
        Sort sort = Sort.by(Sort.Direction.DESC, "createdTime");
        query.with(sort);
        query.with(pageRequest);
        List<UserQaInfo> list = this.mongoTemplate.find(query, UserQaInfo.class);
        list.stream().map(userQaInfo -> {
            Query queryQaInfo = new Query();
            queryQaInfo.addCriteria(Criteria.where("id").is(userQaInfo.getActivityQaInfoId()));
            ActivityQaInfo qaInfo = mongoTemplate.findOne(queryQaInfo, ActivityQaInfo.class);
            if (Objects.nonNull(qaInfo)) {
                userQaInfo.setActivityQaInfoId(qaInfo.getId());
                userQaInfo.setActivityQaInfo(qaInfo);
            }
            return userQaInfo;
        }).collect(Collectors.toList());
        return PageableExecutionUtils.getPage(list, pageRequest, () -> count);
    }

    @Override
    public UserQaInfo findOne(String id) {
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        return mongoTemplate.findOne(query, UserQaInfo.class);
    }

    @Override
    public Query getQaQuery(String userId, String qaInfoId, String activityId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        query.addCriteria(Criteria.where("activityQaInfoId").is(qaInfoId));
        query.addCriteria(Criteria.where("activityId").is(activityId));
        return query;
    }

    private void addPointH5(UserPO currentUser, ActivityQaInfo activityQaInfo) {
        UserParticipateActivityTaskInfo userParticipateActivityTaskInfo = new UserParticipateActivityTaskInfo();
        userParticipateActivityTaskInfo.setActivityId(activityQaInfo.getActivityId());
        ActivityTaskInfo taskInfo = activityTaskService.find(activityQaInfo.getActivityId(), TaskBizType.INVITE);
        userParticipateActivityTaskInfo.setTaskId(taskInfo.getId());
        userParticipateActivityTaskInfo.setBizType(TaskBizType.INVITE);
        ActivityTaskRule activityTaskRule = activityTaskRuleService.find(activityQaInfo.getActivityId(),
                TaskBizType.QA.name());
        if (Objects.nonNull(activityTaskRule)) {
            userParticipateActivityTaskInfo.setQuantity(activityTaskRule.getPoints());
        }
        userParticipateActivityTaskInfo.setUpdatedTime(new Date());
        // 操纵类型0:累加,1:替换
        activityService.updateUserTaskAllRanking(currentUser, userParticipateActivityTaskInfo, 0);
    }

    @Override
    public void checkQaLimit(Integer type, String qaUserId, String qaInfoId) {
        ActivityQaInfo activityQaInfo = this.mongoTemplate.findById(qaInfoId, ActivityQaInfo.class);
        if (type != 4 && (type == 1 && activityQaInfo.getNo() == 1)) {//初赛不进行答题限制
            return;
        }

        Query query = getQaQuery(qaUserId, qaInfoId, activityQaInfo.getActivityId());
        UserQaInfo userQaInfo = this.mongoTemplate.findOne(query, UserQaInfo.class);
        if (Objects.nonNull(userQaInfo)) {
            log.error("【提交答题】用户-> {}参与活动-> {}答题 - > {} 次数-> {}已用完", qaUserId, activityQaInfo.getActivityId(),
                    qaInfoId, userQaInfo.getReTryQaNum());
            if (userQaInfo.getReTryQaNum() > userQaInfo.getTotalQaNum()) {
                String qaTitle = "";
                Integer no = userQaInfo.getNo();
                //旧业务
                if (type == 1) {
                    qaTitle = (no == 2) ? "省赛" : "国赛";
                } else {
                    //新业务
                    switch (no) {
                        case 1:
                            qaTitle = "初赛";
                            break;
                        case 2:
                            qaTitle = "复赛";
                            break;
                        case 3:
                            qaTitle = "决赛";
                            break;
                        default:
                            qaTitle = "该题";
                    }
                }

                throw new QaMaxLimitException(qaTitle + "每人最多回答" + activityQaInfo.getTotalQaNum() + "次，您的次数已用完");
            }
        }

    }

    @Override
    public List<UserQaInviteInfoRes> queryUserQaInviteStatisticsByUserId(String userId) {
        log.info("查询用户答题邀请信息- > {}", userId);
        List<ActivityPlatformConfig> qqActivityList = activityPlatformConfigService.find("qq");
        if (CollectionUtils.isEmpty(qqActivityList)) {
            return new ArrayList<>();
        }
        List<String> activityIdList =
                qqActivityList.stream().map(activityPlatformConfig -> activityPlatformConfig.getActivityId()).collect(Collectors.toList());
        Query query = new Query();
        query.addCriteria(Criteria.where("activityId").in(activityIdList));
        List<ActivityQaInfo> activityQaInfoList = this.mongoTemplate.find(query, ActivityQaInfo.class);
        if (CollectionUtils.isEmpty(activityQaInfoList)) {
            return new ArrayList<>();
        }
        List<UserQaInviteInfoRes> list = new ArrayList<>();
        Map<String, List<ActivityQaInfo>> qaMap =
                activityQaInfoList.stream().collect(Collectors.groupingBy(activityQaInfo -> activityQaInfo.getActivityId()));
        qaMap.forEach((activityId, item) -> {
            UserQaInviteInfoRes info = new UserQaInviteInfoRes();
            ActivityTaskInfo activityTaskInfo = activityTaskService.find(activityId, TaskBizType.INVITE);
            if (Objects.nonNull(activityTaskInfo)) {
                Long inviteUserCount = userInviteRecordService.getInviteUserCount(userId, activityId,
                        activityTaskInfo.getId(), Boolean.TRUE);
                info.setInviteCount(inviteUserCount);
            }
            Optional<ActivityQaInfo> chuSaiQaOptional =
                    item.parallelStream().filter(activityQaInfo -> activityQaInfo.getNo() == 1).findAny();
            if (chuSaiQaOptional.isPresent()) {
                ActivityQaInfo chuSaiActivityQaInfo = chuSaiQaOptional.get();
                info.setActivityName(chuSaiActivityQaInfo.getActivityName());
                Double score = getScoreByUserId(userId, chuSaiActivityQaInfo);
                info.setQaScore(score);

            }
            Optional<ActivityQaInfo> fuSaiQaOptional =
                    item.parallelStream().filter(activityQaInfo -> activityQaInfo.getNo() == 2).findAny();
            if (fuSaiQaOptional.isPresent()) {
                ActivityQaInfo fuSaiActivityQaInfo = fuSaiQaOptional.get();
                info.setActivityName(fuSaiActivityQaInfo.getActivityName());
                Double score = getScoreByUserId(userId, fuSaiActivityQaInfo);
                info.setProvinceQaScore(score);
            }
            Optional<ActivityQaInfo> jueSaiQaOptional =
                    item.parallelStream().filter(activityQaInfo -> activityQaInfo.getNo() == 3).findAny();
            if (jueSaiQaOptional.isPresent()) {
                ActivityQaInfo jueSaiQaActivityQaInfo = jueSaiQaOptional.get();
                info.setActivityName(jueSaiQaActivityQaInfo.getActivityName());
                Double score = getScoreByUserId(userId, jueSaiQaActivityQaInfo);
                info.setCountryQaScore(score);
            }
            info.setActivityId(activityId);
            list.add(info);
        });
        return list;
    }

    @Override
    public ActivityPlusUserQaRes findUserQaInfoByUserIdAndActivityId(UserPO currentUser, Integer contestQaType,
                                                                     String activityId) {
        List<ActivityQaInfo> qaInfoList = this.activityQaInfoService.findByActivityId(activityId);
        if (CollectionUtils.isEmpty(qaInfoList)) {
            throw new BusinessException("当前活动未配置答题信息");
        }
        log.info("【用户参与活动答题】userId - > {} | activityId - > {} | contestQaType- > {}", currentUser.getId(), activityId
                , contestQaType);
        Integer qaNumber_1 = 1;
        Integer qaNumber_2 = 2;
        Integer qaNumber_3 = 3;
        //竞赛专业组
        if (contestQaType == 2) {
            qaNumber_1 = 5;
            qaNumber_2 = 6;
            qaNumber_3 = 7;
        }
        Integer finalQaNumber_1 = qaNumber_1;
        ActivityQaInfo chuSaiActivityQaInfo =
                qaInfoList.parallelStream().filter(activityQaInfo -> activityQaInfo.getNo() == finalQaNumber_1).findFirst().orElse(null);
        if (Objects.isNull(chuSaiActivityQaInfo)) {
            throw new BusinessException("当前活动未配置初赛答题");
        }
        Integer finalQaNumber_2 = qaNumber_2;
        ActivityQaInfo fuSaiActivityQaInfo =
                qaInfoList.parallelStream().filter(activityQaInfo -> activityQaInfo.getNo() == finalQaNumber_2).findFirst().orElse(null);
        if (Objects.isNull(fuSaiActivityQaInfo)) {
            throw new BusinessException("当前活动未配置复赛答题");
        }
        Integer finalQaNumber_3 = qaNumber_3;
        ActivityQaInfo jueSaiActivityQaInfo =
                qaInfoList.parallelStream().filter(activityQaInfo -> activityQaInfo.getNo() == finalQaNumber_3).findFirst().orElse(null);
        if (Objects.isNull(jueSaiActivityQaInfo)) {
            throw new BusinessException("当前活动未配置决赛答题");
        }
        ActivityInfo activityInfo = activityService.findOne(activityId);
        ActivityTaskInfo activityTaskInfo = activityTaskService.find(activityId, TaskBizType.INVITE);
        ActivityPlusUserQaRes activityPlusUserQaRes = new ActivityPlusUserQaRes();
        if (Objects.nonNull(activityTaskInfo)) {
            activityPlusUserQaRes.setTaskId(activityTaskInfo.getId());
        }
        activityPlusUserQaRes.setHasVolunteerInvite(activityInfo.getHasVolunteerInvite());
        activityPlusUserQaRes.setSignUpVolunteerImgUrl(activityInfo.getSignUpVolunteerImgUrl());
        activityPlusUserQaRes.setQaDesc(activityInfo.getQaDesc());
        activityPlusUserQaRes.setActivityDetail(activityInfo.getContestDetail());
        activityPlusUserQaRes.setChuSaiQaPassed(Boolean.TRUE);
        activityPlusUserQaRes.setNonMajorContestDetail(activityInfo.getNonMajorContestDetail());
        activityPlusUserQaRes.setNonMajorQaLink(activityInfo.getNonMajorQaLink());
        activityPlusUserQaRes.setMajorContestDetail(activityInfo.getMajorContestDetail());
        activityPlusUserQaRes.setMajorQaLink(activityInfo.getMajorQaLink());
        activityPlusUserQaRes.setBeforeSignUpDetail(activityInfo.getBeforeSignUpDetail());
        activityPlusUserQaRes.setAfterSignUpDetail(activityInfo.getAfterSignUpDetail());
        activityPlusUserQaRes.setShowScheduleTips(activityInfo.getShowScheduleTips());
        String chuSaiQaId = chuSaiActivityQaInfo.getId();
        activityPlusUserQaRes.setChuSaiQaId(chuSaiQaId);
        activityPlusUserQaRes.setChuSaiText("初赛");
        activityPlusUserQaRes.setChuSaiQaTitle(chuSaiActivityQaInfo.getName());
        activityPlusUserQaRes.setChuSaiQaLockImageUrl(chuSaiActivityQaInfo.getQaLockImageUrl());
        activityPlusUserQaRes.setChuSaiQaUnLockImageUrl(chuSaiActivityQaInfo.getQaUnLockImageUrl());
        activityPlusUserQaRes.setChuSaiQaDetail(chuSaiActivityQaInfo.getDetail());
        activityPlusUserQaRes.setChuSaiPayDesc(activityInfo.getChuSaiPayDesc());
        // 获取支付订单
        List<Integer> statusList = Lists.newArrayList(CourseOrderStatusEnum.PAY_SUCCESS.getValue(),
                CourseOrderStatusEnum.REFUND_APPLY.getValue());
        if (activityInfo.getChuSaiFee() == 0) {
            activityPlusUserQaRes.setChuSaiPay(Boolean.TRUE);
        } else {
            //用户是否已支付初赛订单费用
            UserCourseOrder orderBuyUser = userCourseOrderService.getOrderByUserIdAndStatus(currentUser.getId(),
                    currentUser.getAppId(), chuSaiQaId, statusList);
            if (Objects.nonNull(orderBuyUser)) {
                if (CourseOrderStatusEnum.PAY_SUCCESS.getValue() == orderBuyUser.getStatus()) {
                    activityPlusUserQaRes.setChuSaiPay(Boolean.TRUE);
                }
            }
        }
        String fuSaiQaId = fuSaiActivityQaInfo.getId();
        activityPlusUserQaRes.setFuSaiQaId(fuSaiQaId);
        activityPlusUserQaRes.setFuSaiText("复赛");
        activityPlusUserQaRes.setFuSaiQaTitle(fuSaiActivityQaInfo.getName());
        activityPlusUserQaRes.setFuSaiQaLockImageUrl(fuSaiActivityQaInfo.getQaLockImageUrl());
        activityPlusUserQaRes.setFuSaiQaUnLockImageUrl(fuSaiActivityQaInfo.getQaUnLockImageUrl());
        activityPlusUserQaRes.setFuSaiQaDetail(fuSaiActivityQaInfo.getDetail());
        activityPlusUserQaRes.setFuSaiPayDesc(activityInfo.getFuSaiPayDesc());
        if (activityInfo.getFuSaiFee() == 0) {
            activityPlusUserQaRes.setFuSaiPay(Boolean.TRUE);
        } else {
            //用户是否已支付复订单费用
            UserCourseOrder orderBuyUser = userCourseOrderService.getOrderByUserIdAndStatus(currentUser.getId(),
                    currentUser.getAppId(), fuSaiQaId, statusList);
            if (Objects.nonNull(orderBuyUser)) {
                if (CourseOrderStatusEnum.PAY_SUCCESS.getValue() == orderBuyUser.getStatus()) {
                    activityPlusUserQaRes.setFuSaiPay(Boolean.TRUE);
                }
            }
        }
        String jueSaiQaId = jueSaiActivityQaInfo.getId();
        activityPlusUserQaRes.setJueSaiQaId(jueSaiQaId);
        activityPlusUserQaRes.setJueSaiText("决赛");
        activityPlusUserQaRes.setJueSaiQaTitle(jueSaiActivityQaInfo.getName());
        activityPlusUserQaRes.setJueSaiQaLockImageUrl(jueSaiActivityQaInfo.getQaLockImageUrl());
        activityPlusUserQaRes.setJueSaiQaUnLockImageUrl(jueSaiActivityQaInfo.getQaUnLockImageUrl());
        activityPlusUserQaRes.setJueSaiQaDetail(jueSaiActivityQaInfo.getDetail());
        activityPlusUserQaRes.setJueSaiPayDesc(activityInfo.getJueSaiPayDesc());
        if (activityInfo.getJueSaiFee() == 0) {
            activityPlusUserQaRes.setJueSaiPay(Boolean.TRUE);
        } else {
            //用户是否已支付决赛订单费用
            UserCourseOrder orderBuyUser = userCourseOrderService.getOrderByUserIdAndStatus(currentUser.getId(),
                    currentUser.getAppId(), jueSaiQaId, statusList);
            if (Objects.nonNull(orderBuyUser)) {
                if (CourseOrderStatusEnum.PAY_SUCCESS.getValue() == orderBuyUser.getStatus()) {
                    activityPlusUserQaRes.setJueSaiPay(Boolean.TRUE);
                }
            }
        }
        List<UserQaInfo> userQaInfoList = getUserQaInfos(currentUser, activityId, chuSaiQaId, fuSaiQaId, jueSaiQaId);
        if (CollectionUtils.isEmpty(userQaInfoList)) {
            activityPlusUserQaRes.setJueSaiQaPassed(Boolean.FALSE);
            activityPlusUserQaRes.setFuSaiQaPassed(Boolean.FALSE);
            return activityPlusUserQaRes;
        }
        Optional<UserQaInfo> chuSaiOptional = checkUserQaInfo(chuSaiQaId, userQaInfoList);
        if (chuSaiOptional.isPresent()) {
            activityPlusUserQaRes.setFuSaiQaPassed(Boolean.TRUE);
        }
        Optional<UserQaInfo> fuSaiOptional = checkUserQaInfo(fuSaiQaId, userQaInfoList);
        if (fuSaiOptional.isPresent()) {
            activityPlusUserQaRes.setJueSaiQaPassed(Boolean.TRUE);
            activityPlusUserQaRes.setFuSaiQaPassed(Boolean.TRUE);
        }
        return activityPlusUserQaRes;
    }

    @Override
    public UserCompetitionQa findByUserIdAndScore(QueryQaHomeCommand queryQaHomeCommand) {
        //活动ID
        UserCompetitionQa userCompetitionQa = new UserCompetitionQa();
        String activityId = queryQaHomeCommand.getActivityGroupId();
        String qaInfoId = queryQaHomeCommand.getQaInfoId();
        UserPO currentUser = queryQaHomeCommand.getCurrentUser();
        String userId = queryQaHomeCommand.getCurrentUser().getId();
        userCompetitionQa.setUserId(userId);
        userCompetitionQa.setQaInfoId(qaInfoId);
        userCompetitionQa.setActivityId(activityId);
        userCompetitionQa.setNickName(currentUser.getNickName());
        userCompetitionQa.setAvatarUrl(currentUser.getAvatarUrl());
        ActivityInfo activityInfo = this.activityService.findOne(activityId);
        userCompetitionQa.setQaExercise(activityInfo.getQaExercise());
        userCompetitionQa.setActivityType(activityInfo.getType());
        userCompetitionQa.setHasPaperCa(activityInfo.getHasPaperCa());
        userCompetitionQa.setHasElectronicCa(activityInfo.getHasElectronicCa());
        userCompetitionQa.setDigitalCaReceive(activityInfo.getDigitalCaReceive());
        userCompetitionQa.setDigitalCaNoReceiveDesc(activityInfo.getDigitalCaNoReceiveDesc());
        ActivityQaInfo activityQaInfo = this.mongoTemplate.findById(qaInfoId, ActivityQaInfo.class);
        userCompetitionQa.setQaDetail(activityQaInfo.getDetail());
        userCompetitionQa.setQaChannel(activityQaInfo.getQaChannel());
        userCompetitionQa.setOuterQaLinker(activityQaInfo.getOuterQaLinker());
        UserQaInfo userQaInfo = this.findByUserIdAndQaInfoIdAndActivityId(userId, qaInfoId, activityId);
        if (Objects.nonNull(userQaInfo)) {
            Integer reTryQaNum = userQaInfo.getTotalQaNum() - userQaInfo.getReTryQaNum();
            if (reTryQaNum <= 0 || (userQaInfo.getReTryQaNum() > userQaInfo.getTotalQaNum())) {
                userCompetitionQa.setQaLimit(0);
            } else {
                if (userQaInfo.getBuyQaNum() <= 0) {
                    userCompetitionQa.setQaLimit(reTryQaNum);
                } else {
                    userCompetitionQa.setQaLimit(reTryQaNum);
                }
            }
            if (CollectionUtils.isNotEmpty(userQaInfo.getScoreSet())) {
                userCompetitionQa.setScore(userQaInfo.getScoreSet().stream().collect(Collectors.toList()).stream().max(Comparator.comparing(Double::doubleValue)).get());
            } else {
                userCompetitionQa.setScore(userQaInfo.getQaScore());
            }
            if (CollectionUtils.isNotEmpty(userQaInfo.getUserQaLevelList())) {
                UserQaLevel userQaLevelExist =
                        userQaInfo.getUserQaLevelList().stream().filter(userQaLevel -> userQaLevel.getQaNumber().intValue() == activityQaInfo.getNo().intValue()).max(Comparator.comparing(UserQaLevel::getQsScore)).get();
                if (Objects.nonNull(userQaLevelExist)) {
                    userCompetitionQa.setCaLevel(userQaLevelExist.getLevel());
                }
            }
        } else {
            userCompetitionQa.setQaLimit(activityQaInfo.getTotalQaNum());
        }
        UserParticipateActivityInfo userParticipateActivityInfo =
                this.userParticipateActivityInfoService.findByUserIdActivityId(userId, activityId);
        if (Objects.nonNull(userParticipateActivityInfo)) {
            userCompetitionQa.setName(userParticipateActivityInfo.getName());
            userCompetitionQa.setUniversityId(userParticipateActivityInfo.getUniversityId());
            userCompetitionQa.setUniversityName(userParticipateActivityInfo.getUniversityName());
        }
        List<UserCa> userCaList = userCaService.findByUserIdAndActivityId(userId, activityId);
        if (CollectionUtils.isNotEmpty(userCaList)) {
            QaRuleMatchRes qaRuleMatchRes = competitionQaInfoService.qaRuleByQaInfoId(qaInfoId,
                    userCompetitionQa.getScore());
            String caLevelName = qaRuleMatchRes.getCaLevelName();
            log.info("【答题-证书等级】用户->{}参与答题-> {}历史最高分-> {},等级-> {}", currentUser.getId(),
                    userCompetitionQa.getScore(), caLevelName);
            Optional<UserCa> userCaFirstOptional =
                    userCaList.stream().filter(userCa -> "qa".equals(userCa.getTaskBizType()) && userCa.getCaLevel().equals(caLevelName)).findFirst();
            if (userCaFirstOptional.isPresent()) {
                String caType = userCaFirstOptional.get().getCaType();
                HashMap<String, String> caMatchKeyMap = activityInfo.getCaMatchKeyWords();
                if (MapUtils.isNotEmpty(caMatchKeyMap)) {
                    switch (activityQaInfo.getNo()) {
                        case 1:
                            //初赛匹配
                            String chuSaiKeyWord = caMatchKeyMap.get("c-contest");
                            if (StringUtils.isNotBlank(chuSaiKeyWord)) {
                                caType = chuSaiKeyWord;
                            }
                            break;
                        case 2:
                            //复赛匹配
                            String fuSaiKeyWord = caMatchKeyMap.get("p-contest");
                            if (StringUtils.isNotBlank(fuSaiKeyWord)) {
                                caType = fuSaiKeyWord;
                            }
                            break;
                        case 3:
                            //决赛匹配
                            String jueSaiKeyWord = caMatchKeyMap.get("co-contest");
                            if (StringUtils.isNotBlank(jueSaiKeyWord)) {
                                caType = jueSaiKeyWord;
                            }
                            break;
                        default:

                    }
                }
                userCompetitionQa.setQaType(caType);
                userCompetitionQa.setCaType(caType);
                userCompetitionQa.setCaLevel(caLevelName);

                userCompetitionQa.setReceiveCa(Boolean.TRUE);
                userCompetitionQa.setTips("恭喜获得" + caLevelName);
                //领取电子版需要收费
                if (activityInfo.getContestDigitalCaFee() > 0) {
                    userCompetitionQa.setDigitalCaPay(Boolean.TRUE);
                    userCompetitionQa.setDigitalCaPayDesc(activityInfo.getDigitalCaPayDesc());
                }
            } else {
                userCompetitionQa.setCaLevel("暂无等级");
                userCompetitionQa.setTips("很遗憾！暂不能获得证书");
            }
        } else {
            userCompetitionQa.setTips("很遗憾！暂不能获得证书");
        }
        return userCompetitionQa;
    }

    @Override
    public H5UserQaPracticeRes findUserQaQaPracticeByUserId(UserPO currentUser, String activityId, String qaInfoId) {
        //获取习题信息
        H5UserQaPracticeRes h5UserQaPracticeRes = new H5UserQaPracticeRes();
        ActivityQaInfo qaPracticeInfo = null;
        if (StringUtils.isBlank(qaInfoId)) {
            qaPracticeInfo = activityQaInfoService.findByActivityIdAndQaNumber(activityId, 2);
        } else {
            qaPracticeInfo = activityQaInfoService.findById(qaInfoId);
        }
        if (Objects.isNull(qaPracticeInfo)) {
            return h5UserQaPracticeRes;
        }
        ActivityInfo activityInfo = activityService.findOne(activityId);
        qaInfoId = qaPracticeInfo.getId();
        h5UserQaPracticeRes.setActivityId(activityId);
        h5UserQaPracticeRes.setQaDetail(qaPracticeInfo.getDetail());
        h5UserQaPracticeRes.setQaImageUrl(qaPracticeInfo.getImageUr());
        h5UserQaPracticeRes.setQaInfoId(qaInfoId);
        if (Objects.nonNull(activityInfo)) {
            h5UserQaPracticeRes.setQaExercise(activityInfo.getQaExercise());
        }
        //获取总的题数
        Query query = new Query();
        query.addCriteria(Criteria.where("activityQaInfoId").is(qaPracticeInfo.getId()));
        long qaCount = this.mongoTemplate.count(query, ActivityQuestionInfo.class);
        h5UserQaPracticeRes.setQaCount((int) qaCount);
        //获取用户提交答题记录
        UserCompetitionQaAnswer userCompetitionQaAnswer =
                userCompetitionQaAnswerService.findByUserIdAndQaInfoIdAndActivityId(currentUser.getId(),
                        qaInfoId, activityId);
        if (Objects.isNull(userCompetitionQaAnswer)) {
            return h5UserQaPracticeRes;
        }
        h5UserQaPracticeRes.setQaUserCount(userCompetitionQaAnswer.getAnswersQuestionInfoList().size());

        List<ActivityQuestionInfo> userAnswersQuestionInfoList = userCompetitionQaAnswer.getAnswersQuestionInfoList();
        List<String> userSubmitQuestionIdList =
                userAnswersQuestionInfoList.stream().map(userAnswer -> userAnswer.getId()).collect(Collectors.toList());
        //获取用户错误题数与正确题数
        query = new Query();
        query.addCriteria(Criteria.where("id").in(userSubmitQuestionIdList));
        query.addCriteria(Criteria.where("activityQaInfoId").is(qaInfoId));
        List<ActivityQuestionInfo> questionInfoList = this.mongoTemplate.find(query, ActivityQuestionInfo.class);
        QaInfoScoreResponse userQaInfoScore = competitionQaInfoService.getQaScore(currentUser.getId(), qaInfoId,
                questionInfoList, userAnswersQuestionInfoList);
        h5UserQaPracticeRes.setQaErrorCount(userQaInfoScore.getQaErrorCount());
        h5UserQaPracticeRes.setQaRightCount(userQaInfoScore.getQaRightCount());
        h5UserQaPracticeRes.setQaScore(userQaInfoScore.getQaScore());
        userSubmitQuestionIdList.clear();
        userAnswersQuestionInfoList.clear();
        userQaInfoScore.getUserAnswersRightQuestionInfoList().clear();
        userQaInfoScore.getUserAnswersErrorQuestionInfoList().clear();
        return h5UserQaPracticeRes;
    }

    @Override
    public UserQaPracticeResult doQaPracticeCommit(QaPracticeCommitCommand qaPracticeCommitCommand) {
        UserPO currentUser = qaPracticeCommitCommand.getCurrentUser();
        String activityId = qaPracticeCommitCommand.getActivityId();
        String qaInfoId = qaPracticeCommitCommand.getQaInfoId();
        ActivityQuestionInfo userAnswersQuestionInfo = qaPracticeCommitCommand.getUserAnswersQuestionInfo();
        log.info("【题库练习】userId - > {} 参与活动 -> {} 提交了题库练习信息 - >{}", currentUser.getId(), activityId, qaInfoId);
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(userAnswersQuestionInfo.getId()));
        query.addCriteria(Criteria.where("activityQaInfoId").is(qaInfoId));
        ActivityQuestionInfo questionInfo = this.mongoTemplate.findOne(query, ActivityQuestionInfo.class);
        if (Objects.isNull(questionInfo)) {
            throw new BusinessException("未找到当前答题信息");
        }
        List<ActivityQuestionInfo> userAnswersQuestionInfoList = Arrays.asList(userAnswersQuestionInfo);
        List<ActivityQuestionInfo> questionInfoList = Arrays.asList(questionInfo);
        //提交答题验证答案结果
        QaInfoScoreResponse userQaInfoScore = competitionQaInfoService.getQaScore(currentUser.getId(), qaInfoId,
                questionInfoList, userAnswersQuestionInfoList);
        //答题错误题库
        List<ActivityQuestionInfo> userAnswersErrorQuestionInfoList =
                userQaInfoScore.getUserAnswersErrorQuestionInfoList();
        //答题正确题库
        List<ActivityQuestionInfo> userAnswersRightQuestionInfoList =
                userQaInfoScore.getUserAnswersRightQuestionInfoList();
        UserQaPracticeResult userQaPracticeResult = new UserQaPracticeResult();
        UserCompetitionQaAnswer userCompetitionQaAnswer =
                userCompetitionQaAnswerService.findByUserIdAndQaInfoIdAndActivityId(currentUser.getId(), qaInfoId,
                        activityId);
        if (Objects.isNull(userCompetitionQaAnswer)) {
            //答错题库
            if (CollectionUtils.isNotEmpty(userAnswersErrorQuestionInfoList)) {
                buildUserCommitQuestion(userQaInfoScore, questionInfoList);
                userCompetitionQaAnswer = new UserCompetitionQaAnswer();
                userCompetitionQaAnswer.getAnswersQuestionInfoList().addAll(questionInfoList);
                userCompetitionQaAnswer.setQaInfoId(qaInfoId);
                userCompetitionQaAnswer.setUserId(currentUser.getId());
                userCompetitionQaAnswer.setActivityGroupId(activityId);
            }
            //答对题库
            if (CollectionUtils.isNotEmpty(userAnswersRightQuestionInfoList)) {
                userCompetitionQaAnswer = new UserCompetitionQaAnswer();
                userCompetitionQaAnswer.getAnswersQuestionInfoList().addAll(userAnswersRightQuestionInfoList);
                userCompetitionQaAnswer.setQaInfoId(qaInfoId);
                userCompetitionQaAnswer.setUserId(currentUser.getId());
                userCompetitionQaAnswer.setActivityGroupId(activityId);
            }
        } else {
            List<ActivityQuestionInfo> userQaAnswersQuestionInfoList =
                    userCompetitionQaAnswer.getAnswersQuestionInfoList();
            //用户提交答题是否存在其中
            ActivityQuestionInfo userQaQuestionInfo =
                    userQaAnswersQuestionInfoList.stream().filter(activityQuestionInfo -> activityQuestionInfo.getId().equals(userAnswersQuestionInfo.getId())).findFirst().orElse(null);
            if (Objects.isNull(userQaQuestionInfo)) {
                //不存在，则add
                if (CollectionUtils.isNotEmpty(userAnswersErrorQuestionInfoList)) {
                    userQaAnswersQuestionInfoList.addAll(userAnswersErrorQuestionInfoList);
                }
                if (CollectionUtils.isNotEmpty(userAnswersRightQuestionInfoList)) {
                    userQaAnswersQuestionInfoList.addAll(userAnswersRightQuestionInfoList);
                }
                userCompetitionQaAnswer.setAnswersQuestionInfoList(userQaAnswersQuestionInfoList);
            } else {
                //存在,删除
                userQaAnswersQuestionInfoList = new ArrayList<>(userQaAnswersQuestionInfoList);
                userQaAnswersQuestionInfoList.removeIf(activityQuestionInfo -> activityQuestionInfo.getId().equals(userAnswersQuestionInfo.getId()));
                //不存在，则add
                if (CollectionUtils.isNotEmpty(userAnswersErrorQuestionInfoList)) {
                    userQaAnswersQuestionInfoList.addAll(userAnswersErrorQuestionInfoList);
                }
                if (CollectionUtils.isNotEmpty(userAnswersRightQuestionInfoList)) {
                    userQaAnswersQuestionInfoList.addAll(userAnswersRightQuestionInfoList);
                }
                userCompetitionQaAnswer.setAnswersQuestionInfoList(userQaAnswersQuestionInfoList);
            }
        }
        userCompetitionQaAnswerService.saveOrUpdate(userCompetitionQaAnswer);
        if (CollectionUtils.isEmpty(userAnswersErrorQuestionInfoList) || CollectionUtils.isNotEmpty(userAnswersRightQuestionInfoList)) {
            userQaPracticeResult.setQa(Boolean.TRUE);
            ActivityQuestionInfo activityQuestionInfoRight = userAnswersRightQuestionInfoList.get(0);
            if (Objects.nonNull(activityQuestionInfoRight)) {
                userQaPracticeResult.setQaAnalysis(activityQuestionInfoRight.getQaAnalysis());
                userQaPracticeResult.setUserQaItem(activityQuestionInfoRight.getUserQaItem());
                userQaPracticeResult.setRightQaItem(activityQuestionInfoRight.getRightQaItem());
            }

            userQaInfoScore.getUserAnswersRightQuestionInfoList().clear();
            userQaInfoScore.getUserAnswersErrorQuestionInfoList().clear();
            return userQaPracticeResult;
        }
        ActivityQuestionInfo activityQuestionInfo = userQaInfoScore.getUserAnswersErrorQuestionInfoList().get(0);
        if (Objects.nonNull(activityQuestionInfo)) {
            userQaPracticeResult.setQaAnalysis(activityQuestionInfo.getQaAnalysis());
            userQaPracticeResult.setUserQaItem(activityQuestionInfo.getUserQaItem());
            userQaPracticeResult.setRightQaItem(activityQuestionInfo.getRightQaItem());
        }
        userQaInfoScore.getUserAnswersErrorQuestionInfoList().clear();
        userQaInfoScore.getUserAnswersRightQuestionInfoList().clear();
        return userQaPracticeResult;

    }

    @Override
    public void qaPracticeReset(QaInfoReq qaInfoReq) {
        String activityId = qaInfoReq.getActivityId();
        UserPO currentUser = qaInfoReq.getCurrentUser();
        String qaInfoId = qaInfoReq.getQaInfoId();
        log.info("【清空练习题】userId - > {} qaInfoId - > {} activityId - > {}", currentUser.getId(), qaInfoId, activityId);
        userCompetitionQaAnswerService.remove(currentUser.getId(), qaInfoId, activityId);
    }

    private void buildUserCommitQuestion(QaInfoScoreResponse userQaInfoScore,
                                         List<ActivityQuestionInfo> questionInfoList) {
        if (CollectionUtils.isNotEmpty(userQaInfoScore.getUserAnswersErrorQuestionInfoList())) {
            ActivityQuestionInfo userQuestionInfo = userQaInfoScore.getUserAnswersErrorQuestionInfoList().get(0);
            questionInfoList.stream().forEach(activityQuestionInfo -> {
                if (activityQuestionInfo.getId().equals(userQuestionInfo.getId())) {
                    activityQuestionInfo.setUserQaItem(userQuestionInfo.getUserQaItem());
                    activityQuestionInfo.setQaAnalysis(userQuestionInfo.getQaAnalysis());
                    activityQuestionInfo.setUserQaItem(userQuestionInfo.getUserQaItem());
                    activityQuestionInfo.setRightQaItem(userQuestionInfo.getRightQaItem());
                    activityQuestionInfo.setAnswerInfos(userQuestionInfo.getAnswerInfos());
                }
            });
            return;
        }
        questionInfoList.stream().forEach(activityQuestionInfo -> {
            String qaItem =
                    activityQuestionInfo.getAnswerInfos().stream().filter(activityAnswerInfo -> activityAnswerInfo.getAnswered()).map(activityAnswerInfo -> activityAnswerInfo.getPriority().toString()).collect(Collectors.joining(","));
            activityQuestionInfo.setUserQaRight(Boolean.TRUE);
            activityQuestionInfo.setUserQaItem(qaItem);
            activityQuestionInfo.setRightQaItem(qaItem);
        });
    }

    @Override
    public Page<ActivityQuestionInfo> findUserQaPracticeErrorList(H5QaPracticeErrorQuery h5QaPracticeErrorQuery) {
        String activityId = h5QaPracticeErrorQuery.getActivityId();
        UserPO currentUser = h5QaPracticeErrorQuery.getCurrentUser();
        String qaInfoId = h5QaPracticeErrorQuery.getQaInfoId();
        Integer pageSize = h5QaPracticeErrorQuery.getPageSize();
        Integer pageNo = h5QaPracticeErrorQuery.getPageNo();
        log.info("【错误题库练习回顾】activityId -> {} | userId -> {} | qaInfoId -> {}", activityId, currentUser.getId(),
                qaInfoId);
        UserCompetitionQaAnswer userCompetitionQaAnswer =
                userCompetitionQaAnswerService.findByUserIdAndQaInfoIdAndActivityId(currentUser.getId(), qaInfoId,
                        activityId);
        if (Objects.isNull(userCompetitionQaAnswer)) {
            return new PageImpl<>(new ArrayList<>());
        }

        List<ActivityQuestionInfo> answersQuestionInfoList = userCompetitionQaAnswer.getAnswersQuestionInfoList();
        if (CollectionUtils.isEmpty(answersQuestionInfoList)) {
            return new PageImpl<>(new ArrayList<>());
        }
        ActivityQaInfo activityQaInfo = this.mongoTemplate.findById(qaInfoId, ActivityQaInfo.class);
        List<String> userSubmitQuestionIdList =
                answersQuestionInfoList.stream().map(userAnswer -> userAnswer.getId()).collect(Collectors.toList());
        List<ActivityQuestionInfo> questionInfoList = queryQaInfoId(qaInfoId, userSubmitQuestionIdList);
        QaInfoScoreResponse userQaInfoScore = competitionQaInfoService.getQaScore(currentUser.getId(), qaInfoId,
                questionInfoList, answersQuestionInfoList);
        List<ActivityQuestionInfo> userAnswersErrorQuestionInfoList =
                userQaInfoScore.getUserAnswersErrorQuestionInfoList();
        if (CollectionUtils.isEmpty(userAnswersErrorQuestionInfoList)) {
            return new PageImpl<>(new ArrayList<>());
        }
        PageRequest pageRequest = PageRequest.of(pageNo - 1, pageSize);
        return new PageImpl<>(userAnswersErrorQuestionInfoList.stream().peek(userErrorQa -> userErrorQa.setQaSystemNumber(activityQaInfo.getQaSystemNumber())).skip((pageNo - 1) * pageSize).limit(pageSize).collect(Collectors.toList()), pageRequest, userAnswersErrorQuestionInfoList.size());
    }

    @Override
    public Page<ActivityQuestionInfo> findUserQaLog(H5QaPracticeErrorQuery h5QaPracticeErrorQuery) {
        String activityId = h5QaPracticeErrorQuery.getActivityId();
        UserPO currentUser = h5QaPracticeErrorQuery.getCurrentUser();
        String qaInfoId = h5QaPracticeErrorQuery.getQaInfoId();
        Integer pageSize = h5QaPracticeErrorQuery.getPageSize();
        Integer pageNo = h5QaPracticeErrorQuery.getPageNo();
        log.info("【题库练习log】activityId -> {} | userId -> {} | qaInfoId -> {}", activityId, currentUser.getId(),
                qaInfoId);
        UserCompetitionQaAnswer userCompetitionQaAnswer =
                userCompetitionQaAnswerService.findByUserIdAndQaInfoIdAndActivityId(currentUser.getId(), qaInfoId,
                        activityId);
        if (Objects.isNull(userCompetitionQaAnswer)) {
            return getQuestionInfoPage(activityId, currentUser, qaInfoId, pageSize, pageNo);
        }
        log.info("【题库练习已结束 查找新题库4】activityId -> {} | userId -> {} | qaInfoId -> {}", activityId, currentUser.getId(),
                qaInfoId);
        ActivityQaInfo activityQaInfo = this.mongoTemplate.findById(qaInfoId, ActivityQaInfo.class);
        List<ActivityQuestionInfo> answersQuestionInfoList = userCompetitionQaAnswer.getAnswersQuestionInfoList();
        Query query = new Query();
        query.addCriteria(Criteria.where("activityQaInfoId").is(qaInfoId));
        long qaTotal = this.mongoTemplate.count(query, ActivityQuestionInfo.class);
        PageRequest pageRequest = PageRequest.of(pageNo - 1, pageSize);
        List<ActivityQuestionInfo> pageQuestionInfoList =
                answersQuestionInfoList.stream().skip((pageNo - 1) * pageSize).limit(pageSize).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(pageQuestionInfoList)) {
            return new PageImpl<>(pageQuestionInfoList.stream().peek(activityQuestionInfo -> {
                activityQuestionInfo.setQa(Boolean.TRUE);
                activityQuestionInfo.setQaSystemNumber(activityQaInfo.getQaSystemNumber());
            }).collect(Collectors.toList()), pageRequest, qaTotal);
        }
        log.info("【题库练习已结束 查找新题库】activityId -> {} | userId -> {} | qaInfoId -> {}", activityId, currentUser.getId(),
                qaInfoId);
        return getQuestionInfoPage(activityId, currentUser, qaInfoId, pageSize, pageNo);
    }

    private Page<ActivityQuestionInfo> getQuestionInfoPage(String activityId, UserPO currentUser, String qaInfoId,
                                                           Integer pageSize, Integer pageNo) {
        log.info("【题库练习已结束 查找新题库2】activityId -> {} | userId -> {} | qaInfoId -> {}", activityId, currentUser.getId(),
                qaInfoId);
        QaInfoReq qaInfoReq = new QaInfoReq();
        qaInfoReq.setActivityId(activityId);
        qaInfoReq.setQaInfoId(qaInfoId);
        qaInfoReq.setPageNo(pageNo);
        qaInfoReq.setPageSize(pageSize);
        qaInfoReq.setCurrentUser(currentUser);
        qaInfoReq.setQaType("2");
        UserQaInfoResponse userQaInfo = activityQaInfoService.getQaInfo(qaInfoReq);
        return userQaInfo.getQuestionInfo();
    }

    @Override
    public UserQaScoreResponse doH5PlusQaCommit(QaCommitCommand qaCommitCommand) {
        String qaInfoId = qaCommitCommand.getQaInfoId();
        UserPO currentUser = qaCommitCommand.getCurrentUser();
        String userId = currentUser.getId();
        List<ActivityQuestionInfo> userAnswersQuestionInfoList = qaCommitCommand.getUserAnswersQuestionInfoList();
        log.info("【H5新版答题提交】userId -> {} | qaInfoId -> {}", currentUser.getId(), qaInfoId);
        Boolean existLockKey = redisTemplate.opsForValue().setIfAbsent(String.format(USER_QA_LOCK, userId, qaInfoId),
                "1", 4L, TimeUnit.SECONDS);
        if (Objects.nonNull(existLockKey) && !existLockKey) {
            log.info("【H5新版答题提交-重复提交频繁】userId -> {} | qaInfoId -> {}", currentUser.getId(), qaInfoId);
            throw new BusinessException("对不起哦，服务繁忙,稍后重试");
        }
        //校验答题是否已
        this.checkQaLimit(3, userId, qaInfoId);
        ActivityQaInfo activityQaInfo = this.mongoTemplate.findById(qaInfoId, ActivityQaInfo.class);
        //题库信息ID可能包含B套题和C套题ID集合
        List<String> userSubmitQuestionIdList =
                userAnswersQuestionInfoList.stream().map(userAnswer -> userAnswer.getId()).collect(Collectors.toList());
        //先去查询一部分题存在A
        List<ActivityQuestionInfo> questionInfoListA = queryQaInfoId(qaInfoId, userSubmitQuestionIdList);
        //用户提交答题一部分答题
        List<ActivityQuestionInfo> userAnswersQuestionInfoListA =
                userAnswersQuestionInfoList.stream().filter(userAnswer -> userAnswer.getActivityQaInfoId().equals(qaInfoId)).collect(Collectors.toList());
        //先去查询一部分题存在A
        List<String> questionInfoIdListA =
                questionInfoListA.stream().map(ActivityQuestionInfo::getId).collect(Collectors.toList());
        //计算A套题答题分数
        QaInfoScoreResponse userQaInfoScoreA = competitionQaInfoService.getQaScore(userId, qaInfoId,
                questionInfoListA, userAnswersQuestionInfoListA);
        log.info("【H5新版答题提交】A 套题 userId - > {} | activityId - > {}| qaInfoId - > {}| score -> {}", userId,
                activityQaInfo.getActivityId(), qaInfoId, userQaInfoScoreA.getQaScore());
        //去除相同部分-用户提交答题B
        Integer qaScoreB = 0;
        List<String> userSubmitQuestionIdListB = ListUtils.subtract(userSubmitQuestionIdList, questionInfoIdListA);
        if (CollectionUtils.isNotEmpty(userSubmitQuestionIdListB)) {
            String questionIdB = userSubmitQuestionIdListB.get(0);
            ActivityQuestionInfo userQuestionInfoB =
                    userAnswersQuestionInfoList.stream().filter(activityQuestionInfo -> activityQuestionInfo.getId().equals(questionIdB)).findFirst().orElse(null);
            if (Objects.nonNull(userQuestionInfoB)) {
                //计算B套题分数
                List<ActivityQuestionInfo> questionInfoListB = queryQaInfoId(userQuestionInfoB.getActivityQaInfoId(),
                        userSubmitQuestionIdListB);
                List<ActivityQuestionInfo> userAnswersQuestionInfoListB =
                        userAnswersQuestionInfoList.stream().filter(userAnswer -> userAnswer.getActivityQaInfoId().equals(userQuestionInfoB.getActivityQaInfoId())).collect(Collectors.toList());
                QaInfoScoreResponse userQaInfoScoreB = competitionQaInfoService.getQaScore(userId,
                        userQuestionInfoB.getActivityQaInfoId(), questionInfoListB, userAnswersQuestionInfoListB);
                qaScoreB = userQaInfoScoreB.getQaScore().intValue();
                log.info("【H5新版答题提交】B 套题 userId - > {} | activityId - > {}| qaInfoId - > {}| score -> {}", userId,
                        activityQaInfo.getActivityId(), qaInfoId, qaScoreB);
                userQaInfoScoreB.getUserAnswersRightQuestionInfoList().clear();
                userQaInfoScoreB.getUserAnswersErrorQuestionInfoList().clear();
            }
        }
        Integer qaScore = userQaInfoScoreA.getQaScore().intValue() + qaScoreB;
        log.info("【H5新版答题提交】AB 套题 总分 userId - > {} | activityId - > {}| qaInfoId - > {}| score -> {}", userId,
                activityQaInfo.getActivityId(), qaInfoId, qaScore);
        QaRuleMatchRes qaRuleMatchRes = competitionQaInfoService.qaRuleByQaInfoId(qaInfoId, (double) qaScore);
        log.info("【H5新版答题提交】用户->{}参与了答题 - > {} | 分数->{} 等级 - > {}", currentUser.getId(), qaInfoId, qaScore,
                qaRuleMatchRes.getCaLevelName());
        Double passQaScore = activityQaInfo.getPassQaScore();
        Date now = new Date();
        //保持答题信息
        Query query = getQaQuery(userId, qaInfoId, activityQaInfo.getActivityId());
        Update update = new Update();
        UserQaInfo existsUserQaInfo = this.mongoTemplate.findOne(query, UserQaInfo.class);
        if (Objects.isNull(existsUserQaInfo)) {
            update.set("createdTime", now);
            update.set("qaScore", qaScore);
            if (qaScore.intValue() >= passQaScore.intValue()) {
                update.set("passed", Boolean.TRUE);
            } else {
                update.set("passed", Boolean.FALSE);
            }
        }
        UserQaLevel userQaLevel = new UserQaLevel();
        userQaLevel.setActivityQaInfoId(activityQaInfo.getId());
        userQaLevel.setQaNumber(activityQaInfo.getNo());
        userQaLevel.setQsScore(qaScore.doubleValue());
        userQaLevel.setLevel(qaRuleMatchRes.getCaLevelName());
        userQaLevel.setHighestLevel(qaRuleMatchRes.getHighestLevel());
        update.push("scoreSet", qaScore);
        update.push("userQaLevelList", userQaLevel);
        update.set("updatedTime", now);
        update.set("activityName", activityQaInfo.getActivityName());
        update.set("status", "1");
        update.inc("reTryQaNum", 1);
        update.set("totalQaNum", activityQaInfo.getTotalQaNum());
        update.set("caName", qaRuleMatchRes.getCaLevelName());
        update.set("no", activityQaInfo.getNo());
        if (Objects.nonNull(existsUserQaInfo) && qaScore >= existsUserQaInfo.getQaScore().intValue()) {
            update.set("qaScore", qaScore);
            if (qaScore.intValue() >= passQaScore.intValue()) {
                update.set("passed", Boolean.TRUE);
            } else {
                update.set("passed", Boolean.FALSE);
            }
        }
        UserQaScoreResponse userQaScore = new UserQaScoreResponse();
        userQaScore.setQaScore(qaScore);
        userQaScore.setButtonText("返回活动");
        FindAndModifyOptions findAndModifyOptions = new FindAndModifyOptions();
        findAndModifyOptions.upsert(Boolean.TRUE);
        findAndModifyOptions.returnNew(Boolean.TRUE);
        UserQaInfo userQaInfo = this.mongoTemplate.findAndModify(query, update, findAndModifyOptions, UserQaInfo.class);
        if (Objects.isNull(userQaInfo) || qaScore < passQaScore.intValue()) {
            userQaScore.setTipsScore("很遗憾，暂未获奖");
            userQaScore.setRestQa(Boolean.TRUE);
            return userQaScore;
        }
        userQaScore.setTipsScore("恭喜，获得" + qaRuleMatchRes.getCaLevelName());
        //移除选题
        query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        query.addCriteria(Criteria.where("activityQaInfoId").is(qaInfoId));
        query.addCriteria(Criteria.where("activityId").is(activityQaInfo.getActivityId()));
        this.mongoTemplate.remove(query, UserQuestionInfo.class);
        userQaInfoScoreA.getUserAnswersErrorQuestionInfoList().clear();
        userQaInfoScoreA.getUserAnswersRightQuestionInfoList().clear();
        UserParticipateActivityInfo userParticipateActivityInfo =
                this.userParticipateActivityInfoService.findByUserIdActivityId(userId, activityQaInfo.getActivityId());
        if (Objects.nonNull(userParticipateActivityInfo)) {
            userParticipateActivityInfo.setCountryQaScore(userQaScore.getQaScore().doubleValue());
            this.userParticipateActivityInfoService.saveOrUpdate(userParticipateActivityInfo);
        }

        return userQaScore;
    }

    @Override
    public List<ActivityQuestionInfo> queryQaInfoId(String qaInfoId, List<String> userSubmitQuestionIdList) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").in(userSubmitQuestionIdList));
        query.addCriteria(Criteria.where("activityQaInfoId").is(qaInfoId));
        List<ActivityQuestionInfo> questionInfoList = this.mongoTemplate.find(query, ActivityQuestionInfo.class);
        if (CollectionUtils.isEmpty(questionInfoList)) {
            throw new BusinessException("未找到答题信息");
        }
        ActivityQaInfo activityQaInfo = this.mongoTemplate.findById(qaInfoId, ActivityQaInfo.class);
        return questionInfoList.stream().peek(activityQuestionInfo -> activityQuestionInfo.setQaSystemNumber(activityQaInfo.getQaSystemNumber())).collect(Collectors.toList());
    }

    private Optional<UserQaInfo> checkUserQaInfo(String chuSaiQaId, List<UserQaInfo> userQaInfoList) {
        return userQaInfoList.stream().filter(userQaInfo -> userQaInfo.getActivityQaInfoId().equals(chuSaiQaId) && userQaInfo.getPassed()).findFirst();
    }

    private List<UserQaInfo> getUserQaInfos(UserPO currentUser, String activityId, String chuSaiQaId,
                                            String fuSaiQaId, String jueSaiQaId) {
        if (Objects.isNull(currentUser)) {
            return null;
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(currentUser.getId()));
        query.addCriteria(Criteria.where("activityQaInfoId").in(chuSaiQaId, fuSaiQaId, jueSaiQaId));
        query.addCriteria(Criteria.where("activityId").is(activityId));
        return this.mongoTemplate.find(query, UserQaInfo.class);
    }

    private Double getScoreByUserId(String userId, ActivityQaInfo activityQaInfo) {
        UserQaInfo userQaInfo = this.findByUserIdAndQaInfoIdAndActivityId(userId, activityQaInfo.getId(),
                activityQaInfo.getActivityId());
        if (Objects.nonNull(userQaInfo)) {
            return userQaInfo.getQaScore();
        }
        return 0D;
    }

    @Override
    public UserQaInfo findByUserIdAndQaInfoIdAndActivityId(String userId, String qaInfoId, String activityId) {
        log.info("【答题信息】userId -> {} qaInfoId- > {} activityId- > {}", userId, qaInfoId, activityId);
        Query query = getQaQuery(userId, qaInfoId, activityId);
        return this.mongoTemplate.findOne(query, UserQaInfo.class);
    }

    @Override
    public Map<String, Object> batchImportQaRecord(byte[] inputStream, String fileName, String activityId, String qaInfoId) {
        log.info("orderImport fileName {}", fileName);
        try {
            Map<String, Object> result = new HashMap<>();
            List<UserQaImportDomain> models = ExcelUtil.readData(new ByteArrayInputStream(inputStream), UserQaImportDomain.class);
            result.put("allCount", models.size());
            int matchCount = 0;
            int notMatchCount = 0;
            int errorInfo = 0;
            List<Integer> notMatchRows = new ArrayList<>();
            for (int i = 0; i < models.size(); i++) {
                UserQaImportDomain model = models.get(i);
                if (Objects.isNull(model) || StringUtils.isBlank(model.getName()) || StringUtils.isBlank(model.getMobile())) {
                    continue;
                }
                QaCommitCommand qaCommitCommand = new QaCommitCommand();
                qaCommitCommand.setQaScore(model.getScore());
                qaCommitCommand.setQaInfoId(qaInfoId);
                UserParticipateActivityInfo up = userParticipateActivityInfoService.findByMobile(activityId, model.getMobile(), Boolean.TRUE);
                if (Objects.isNull(up)) {
                    log.error(":>>> 用户:{},活动未报名:{}", model.getMobile(),
                            activityId);
                    continue;
                }
                UserPO currentUser = new UserPO();
                currentUser.setAppId(up.getAppId());
                currentUser.setOpenId(up.getOpenId());
                currentUser.setId(up.getUserId());
                currentUser.setUniversityId(up.getUniversityId());
                currentUser.setUniversityName(up.getUniversityName());
                qaCommitCommand.setCurrentUser(currentUser);
                wechatMiniQaService.importQaCommit(qaCommitCommand);
            }
            result.put("matchCount", matchCount);
            result.put("notMatchCount", notMatchCount);
            result.put("notMatchRows", notMatchRows);
            result.put("errorInfo", errorInfo);
            result.put("tips", "列序号从0(A列)开始,第1列姓名(A列)、第2列(B列)电话、第3列(C列)分数不能为空!");
            return result;
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("orderImport error fileName {}", fileName, e);
            return null;
        }
    }

    private void addPoint(UserPO currentUser, String activityId) {
        ActivityTaskRule activityTaskRule = activityTaskRuleService.find(activityId, "QA");
        if (Objects.isNull(activityTaskRule)) {
            return;
        }
        log.info("【用户答题增加积分】userId ->{} activityId-> {} point - > {}", currentUser.getId(), activityId,
                activityTaskRule.getPoints());
        //增加积分
        Double quantity = 0D;
        userActivityPointRankingService.updatePoint(currentUser, activityId, activityTaskRule.getPoints().intValue());
        UserActivityPointRanking userActivityPointRanking = userActivityPointRankingService.find(currentUser.getId(),
                "", activityId);
        if (Objects.nonNull(userActivityPointRanking)) {
            quantity = userActivityPointRanking.getQuantity();
        }
        generateUserCaService.generateUserCa(activityId,
                quantity.intValue() + activityTaskRule.getPoints().intValue(), currentUser);

    }

    @Override
    public void deleteByUserIdAndActivityId(String userId, String activityId) {
        log.info("deleteByUserIdAndActivityId userId:{},activityId:{}", userId, activityId);
        Query query = Query.query(
                Criteria.where("userId").is(userId)
                        .and("activityId").is(activityId));
        DeleteResult deleteResult = this.mongoTemplate.remove(query, UserQaInfo.class);
        log.info("deleteByUserIdAndActivityId deleteResult:{}", JSONObject.toJSONString(deleteResult));

    }
}